#include <windows.h>
#include "EnableDebugPrivileges.h"
#include "FileDialogs.h"

int main(int argc, char** argv)
{
	HANDLE thread;
	char wndName[] = "Halo";
	void* dllPathPtrRemote;
	HANDLE injectedDllModule;
	HWND wnd;
	DWORD pid;
	HANDLE p;

	TCHAR* dllPath = NULL;
	BOOL freeFilePath = FALSE;
	if (argc == 1)
	{
		static const TCHAR  catagory [] = TEXT("DLL");
		static const TCHAR* exts [] = {TEXT("dll"), NULL};

SelectFileWithDialog:
		if (!(dllPath = OpenFileDlg(catagory, exts, NULL)))
			return -1;
	}
	else
	{
		int i;
		for (i = 1; i <= argc; ++i)
		{
			if (GetFileAttributesA(argv[i]) != INVALID_FILE_ATTRIBUTES)
			{
#ifndef UNICODE
				dllPath = argv[i];
#else
				unsigned int argvLen, j;

				freeFilePath = TRUE;
				argvLen = strlen(argv[i]);
				dllPath = (TCHAR*)malloc(sizeof(TCHAR) * argvLen);
				for (j = 0; j < argvLen; ++j)
					dllPath[j] = (TCHAR)argv[i][j];
				dllPath[j] = (TCHAR)'\0';
#endif
			}
		}

		if (dllPath == NULL)
			goto SelectFileWithDialog;
	}

	if (freeFilePath)
		free(dllPath);

	EnableDebugPrivileges();
	wnd = FindWindow(NULL, wndName);
	GetWindowThreadProcessId(wnd, &pid);
	p = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);

	// Allocate memory in the remote process for dllPath
	dllPathPtrRemote = VirtualAllocEx(p, NULL, strlen(dllPath), MEM_COMMIT, PAGE_READWRITE);
	
	// Write dllPath to the allocated memory
	WriteProcessMemory(p, dllPathPtrRemote, (void*)dllPath, strlen(dllPath), NULL);

	// Load dll into the remote process
	thread = CreateRemoteThread(p, NULL, 0x1000,
		                         (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("Kernel32"), "LoadLibraryA"),
								 dllPathPtrRemote, 0, NULL);
	
	// Wait for the dll to be loaded
	WaitForSingleObject(thread, INFINITE);

	// Get handle of the loaded module
	GetExitCodeThread(thread, (LPDWORD)&injectedDllModule);

	CloseHandle(thread);
	VirtualFreeEx(p, dllPathPtrRemote, sizeof(dllPath), MEM_RELEASE);
	return 0;
}